#pragma once

#include <cstdint>
#include <vector>
#include <string>
#include <variant>
#include <optional>
#include <stdexcept>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <tuple>
#include <numeric>
#include "../../db_common.h"
#include "../../DB-OS/page.h"

// =======================================================================
// 类型定义
// =======================================================================
// Row是Value的集合
using Row = std::vector<Value>;

inline Page cal_page;

const uint32_t REAL_PAGE_SIZE = cal_page.get_data_size();

// =======================================================================
// 枚举和结构体
// =======================================================================

// 定义页存储的数据类型
enum class PageType
{
    BPLUS_INTERNAL_PAGE, // 存储<键,页ID>对
    BPLUS_LEAF_PAGE,     // 存储<键,数据>对(数据可以是完整行或主键)
    SYSTEM_PAGE,         // 保留给元数据使用
    UNKNOWN_PAGE
};

/**
 * @class DBPage
 * @brief 管理16KB的数据页，表示B+树的一个节点
 *
 * 这个类直接操作原始字节缓冲区，模拟真实的数据库存储引擎工作方式。
 * 它使用"槽式页"布局。
 *
 * 页布局:
 * -------------------------------------------------------------------------------------
 * | 页头 | 记录1 | 记录2 | ... | 空闲空间 | ... | 槽2 | 槽1 |
 * -------------------------------------------------------------------------------------
 *  ^            ^                                       ^                  ^
 *  0            sizeof(PageHeader)                      free_space_ptr     REAL_PAGE_SIZE
 *
 *  - 页头: 固定大小的元数据，位于页开始处
 *  - 记录: 从页开始处向前增长
 *  - 槽数组: 从页末尾向后增长。每个槽指向一个记录
 *  - 空闲空间: 最后一个记录和第一个槽之间的间隙
 */
class DBPage
{
private:
    // 页头结构，总是位于偏移0处
    struct PageHeader
    {
        uint32_t page_id{INVALID_PAGE_ID};          // 页ID
        uint32_t parent_page_id{INVALID_PAGE_ID};   // 父页ID
        PageType page_type{PageType::UNKNOWN_PAGE}; // 页类型
        uint16_t level{0};                          // B+树层级(0表示叶子节点)
        uint16_t num_records{0};                    // 页上的记录/键数量
        uint32_t free_space_ptr{0};                 // 空闲空间起始偏移

        // 仅对叶子页有意义
        uint32_t prev_page_id{INVALID_PAGE_ID}; // 前一页ID
        uint32_t next_page_id{INVALID_PAGE_ID}; // 后一页ID

        uint32_t leftmost_child_page_id{INVALID_PAGE_ID}; // 最左指针,仅对 BPLUS_INTERNAL_PAGE 有意义
        uint32_t checksum{0};                             // 数据完整性校验
    };

    // 槽结构，指向页内的记录。槽数组位于页末尾
    struct Slot
    {
        uint16_t offset; // 记录从页开始的偏移量
        uint16_t size;   // 记录大小(字节)
    };

    // 整个页的原始数据缓冲区
    std::vector<uint8_t> data_;

    // =======================================================================
    // 私有辅助函数
    // =======================================================================

    // 获取页头指针
    PageHeader *getHeader() { return reinterpret_cast<PageHeader *>(data_.data()); }
    const PageHeader *getHeader() const { return reinterpret_cast<const PageHeader *>(data_.data()); }

    // 获取指定索引的槽
    Slot *getSlot(int index) { return reinterpret_cast<Slot *>(data_.data() + REAL_PAGE_SIZE - (index + 1) * sizeof(Slot)); }
    const Slot *getSlot(int index) const { return reinterpret_cast<const Slot *>(data_.data() + REAL_PAGE_SIZE - (index + 1) * sizeof(Slot)); }

    // 获取记录数据指针
    uint8_t *getRecordData(int index) { return data_.data() + getSlot(index)->offset; }
    const uint8_t *getRecordData(int index) const { return data_.data() + getSlot(index)->offset; }

    // 获取空闲空间大小
    uint32_t getFreeSpaceSize() const;

    // 行序列化辅助函数
    size_t calculateRowSize(const Row &row) const;
    void serializeRow(uint8_t *buffer, const Row &row) const;
    void deserializeRow(const uint8_t *buffer, uint16_t size, Row &row) const;

    // 键序列化辅助函数
    // 计算键的大小
    size_t getSerializedKeySize(const BPlusTreeKey &key) const;

    // 将键序列化到缓冲区
    void serializeKey(uint8_t *buffer, const BPlusTreeKey &key) const;

    // 从缓冲区读取键
    BPlusTreeKey deserializeKey(const uint8_t *buffer) const;

    // 底层记录插入
    bool insertRecord(int index, const uint8_t *record_data, uint16_t record_size, bool &is_space_enough);

    // 获取一条记录的完整数据和大小
    std::pair<const uint8_t *, uint16_t> GetRecord(int index) const;

public:
    // =======================================================================
    // 构造函数和初始化
    // =======================================================================
    DBPage();
    void initialize(uint32_t page_id, PageType page_type, uint16_t level, uint32_t parent_page_id = INVALID_PAGE_ID);
    explicit DBPage(std::vector<uint8_t> &&data);

    // =======================================================================
    // 通用B+树节点API
    // =======================================================================
    bool isLeaf() const { return getHeader()->page_type == PageType::BPLUS_LEAF_PAGE; }
    bool isRoot() const { return getHeader()->parent_page_id == INVALID_PAGE_ID; }
    uint16_t getNumRecords() const { return getHeader()->num_records; }
    uint32_t getPageId() const { return getHeader()->page_id; }
    uint32_t getParentPageId() const { return getHeader()->parent_page_id; }
    void setParentPageId(uint32_t parent_id)
    {
        getHeader()->parent_page_id = parent_id;
        updateChecksum();
    }
    // 是否富余
    bool isSurplus() const
    {
        if (isRoot())
        {
            return false;
        }

        // 可用于存储记录和槽的总空间
        const uint32_t total_data_space = REAL_PAGE_SIZE - sizeof(PageHeader);

        // 当前记录和槽占用的总空间
        const uint32_t current_data_space =
            (getHeader()->free_space_ptr - sizeof(PageHeader)) +
            (getHeader()->num_records * sizeof(Slot));

        // 使用整数乘法避免浮点数和除法截断问题。
        // 如果当前占用空间大于总可用空间的一半，则认为富余。
        return current_data_space * 2 > total_data_space;
    }
    // 通用的删除记录的方法
    void DeleteRecord(int index);
    uint32_t findChildPage(const BPlusTreeKey &key) const;
    // 移动当前页的一半记录到目标页
    std::optional<BPlusTreeKey> MoveHalfTo(DBPage *recipient);

    uint32_t getLeftmostPointer() const;
    void setLeftmostPointer(uint32_t page_id);
    // =======================================================================
    // 内部节点API(键->页ID)
    // =======================================================================
    BPlusTreeKey getInternalKey(int index) const;
    uint32_t getInternalValue(int index) const;
    bool insertInternal(BPlusTreeKey key, uint32_t child_page_id, bool &is_space_enough);
    bool insertInternal(int index, BPlusTreeKey key, uint32_t child_page_id, bool &is_space_enough);
    int findInternalKeyIndex(BPlusTreeKey key) const;
    bool checkSpaceForLeafInsertion(const BPlusTreeKey &key, const std::variant<Row, BPlusTreeKey> &value) const;
    BPlusTreeKey getKey(int index) const
    {
        const uint8_t *record_ptr = getRecordData(index);
        return deserializeKey(record_ptr);
    }
    bool checkSpaceForInternalInsertion(const BPlusTreeKey &key) const;
    PageType getPageType() const { return getHeader()->page_type; }
    /**
     * @brief 判断页是否下溢（空间占用率低于阈值）。
     *        这是触发 B+ 树合并或重分配的条件。
     * @param threshold 阈值，例如 0.5 表示 50%。
     * @return true 如果空间占用率低于阈值。
     */
    bool IsUnderflow(double threshold = 0.5) const;

    // 从兄弟节点移动一条记录到当前节点
    void MoveRecordFrom(DBPage *sibling_page, int sibling_index, int dest_index);

    // 将当前节点的所有记录移动到目标节点
    void MoveAllTo(DBPage *recipient_page);

    // 获取/设置最后一条记录的键
    BPlusTreeKey getLastKey() const
    {
        return getKey(getNumRecords() - 1);
    }

    // 获取/设置第一条记录的键
    BPlusTreeKey getFirstKey() const
    {
        return getKey(0);
    }
    void setKey(int index, const BPlusTreeKey &key, bool is_leaf = true)
    {
        if (is_leaf)
        {
            Row row;
            bool success = getLeafValue(index, row);
            if (success)
            {
                DeleteRecord(index);
                bool is_space_enough = true;
                insertLeaf(index, key, row, is_space_enough);
            }
        }
        else
        {
            auto internal_value = getInternalValue(index);
            DeleteRecord(index);
            bool is_space_enough = true;
            insertInternal(index, key, internal_value, is_space_enough);
        }
    }
    void setLeafValue(int index, const Row &row)
    {
        // 1. 删除旧记录
        DeleteRecord(index);
        // 2. 插入新记录
        bool is_space_enough = true;
        insertLeaf(index, getKey(index), row, is_space_enough);
    }
    // =======================================================================
    // 叶子节点API(键->数据)
    // =======================================================================
    BPlusTreeKey getLeafKey(int index) const;

    // 聚集索引的重载(读取完整行)
    bool getLeafValue(int index, Row &row) const;

    // 二级索引的重载(读取主键)
    BPlusTreeKey getLeafValue(int index) const;

    // 聚集索引的插入重载
    bool insertLeaf(const BPlusTreeKey &key, const Row &row, bool &is_space_enough);
    bool insertLeaf(int index, const BPlusTreeKey &key, const Row &row, bool &is_space_enough);

    // 二级索引的插入重载
    bool insertLeaf(const BPlusTreeKey &secondary_key, const BPlusTreeKey &primary_key, bool &is_space_enough);

    bool insertLeaf(int index, const BPlusTreeKey &secondary_key, const BPlusTreeKey &primary_key, bool &is_space_enough);
    int findLeafKeyIndex(BPlusTreeKey key) const;

    // 叶子节点链表指针
    uint32_t getPrevPageId() const { return getHeader()->prev_page_id; }
    void setPrevPageId(uint32_t prev_id)
    {
        getHeader()->prev_page_id = prev_id;
        updateChecksum();
    }
    uint32_t getNextPageId() const { return getHeader()->next_page_id; }
    void setNextPageId(uint32_t next_id)
    {
        getHeader()->next_page_id = next_id;
        updateChecksum();
    }
    uint16_t getLevel() const { return getHeader()->level; }
    void setLevel(uint16_t level)
    {
        getHeader()->level = level;
        updateChecksum();
    }
    int findChildIndex(uint32_t child_page_id) const;
    // =======================================================================
    // 序列化、验证和调试
    // =======================================================================
    const std::vector<uint8_t> &serialize() const { return data_; }
    void updateChecksum();
    bool validate() const;
    void printMetaInfo() const;
};
